#ifndef CQUADTREENODE_H
#define CQUADTREENODE_H

#include "CQuadTreePosItem.h"
#include <SFML/Graphics/Shape.hpp>
#include <SFML/Graphics.hpp>


/* Main Quad Tree Tree Structure */

class CQuadTreeNode
{
    public:
        enum { TOPLEFT, TOPRIGHT, BOTTOMLEFT, BOTTOMRIGHT };

        CQuadTreeNode(CQuadTreeNode* parentNode, CRect rect, const int maxItems, unsigned int d); //ctor

        ~CQuadTreeNode(); //dtor

        //CQuadTreeNode(const CQuadTreeNode& c); //copy ctor
        void Render(sf::RenderWindow& App)
        {
            sf::Shape poly;

            poly.AddPoint(Vec2fToSFVec(rect_.GetTopLeft()));
            poly.AddPoint(Vec2fToSFVec(rect_.GetBottomLeft()));
            poly.AddPoint(Vec2fToSFVec(rect_.GetBottomRight()));
            poly.AddPoint(Vec2fToSFVec(rect_.GetTopRight()));
            poly.SetOutlineWidth(2);
            poly.EnableFill(false);
            poly.EnableOutline(true);

            for (unsigned int i = 0; i < children_.size(); ++i)
            {
                children_[i]->Render(App);
            }

            App.Draw(poly);
        }

        /* Insertion Methods */
        //insert item in this node
        void Insert(CQuadTreePosItem* item);

        //inserts item in one of the children
        bool InsertInChild(CQuadTreePosItem* item);

        //push an item at index i down to one of the children
        bool PushItemDown(int i);

        //push an item at index i up to parent
        void PushItemUp(int i);
        
        //pushes all items contained up to parent
        void PushAllItemsUp();

        //repartitions node to four quads
        bool Partition();

        /* Query Methods */
        //gets list of items containing this point
        void QueryItems(const Vec2f& point, vector<CQuadTreePosItem* >& itemsFound);

        //gets list of items intersecting rect
        void QueryItems(const CRect& r, vector<CQuadTreePosItem* >& itemsFound);
        
        //DEBUG/Dave
        bool DebugContainsPt(const Vec2f& point);
        bool DebugDeepestNodeContainingPt(const Vec2f& point);
        
        //DEBUG/Dave
        void DebugQueryItems(const Vec2f& point, vector<CQuadTreePosItem* >& itemsFound, Vec2f& identifier, unsigned int& debugDepth);
        void DebugQueryItemsInParent(const Vec2f& point, vector<CQuadTreePosItem* >& itemsFound, Vec2f& identifier, unsigned int& debugDepth);
        
        //DEBUG/Dave
        void DebugPrintItems();

        //gets list of all items in this node
        void GetAllItems(vector<CQuadTreePosItem* >& itemsFound);

        //Finds node containing this item
        CQuadTreeNode* FindItemNode(CQuadTreePosItem* item);

//        //removes item from this node
//        void RemoveItem(CQuadTreePosItem* item);

        //removes item from this node at index
        void RemoveItem(unsigned int i);


        /* Misc */
        //updates item movement stuff
        void ItemMove(CQuadTreePosItem* item);

        //tests if this node contains the rect
        bool ContainsRect(const CRect& r);

        //traverses the graph to find existence of one item in children
        bool IsEmpty();

        //sees if children are empty, if so deletes them
        void FlushChildren();

        //destroys the kids
        void DestroyChildren();

        //searches *upward* to find a new leaf for a position item that has moved
        CQuadTreeNode* FindNewNode(const CRect& r);

        //compares two objects
        bool operator==(const CQuadTreeNode& n) const;


        /* ----- */

        //getters
        CRect& GetRect();

    protected:
        const static unsigned int MAX_DEPTH = 7;

        vector<CQuadTreePosItem*> items_;     //items in this node
        CRect rect_;                          //bounding Rect for this node
        int maxItems_;                        //max items in this node
        bool isPartitioned_;                  //true is this not a leaf node
        CQuadTreeNode* parent_;               //pointer to parent node
        vector<CQuadTreeNode*> children_;     //pointers to children .. may be null
        unsigned int depth_;
        bool verbose_;                        //debugging tool

};


#endif // CQUADTREENODE_H
